package main

import (
	"fmt"
	"io/ioutil"
	"strconv"
	"strings"

	"github.com/Luxurioust/excelize" //用于结束后暂停
)

import (
	termbox "github.com/nsf/termbox-go" //用于结束后暂停
)

//用于结束后暂停
func init() {
	if err := termbox.Init(); err != nil {
		panic(err)
	}
	termbox.SetCursor(0, 0)
	termbox.HideCursor()
}

//默认路径 同级
const (
	excelPath  string = "./excel"
	excelOther string = "./excelOther"
	luaPath           = "./lua"
	jsonPath          = "./json"

	tbHead      = "ltbConf"
	luaFileHead = "/Conf"
)

//加载 遍历 ./excel 下的所有目录
func loadExcels() {
	//得到文件列表
	files, _ := ioutil.ReadDir(excelPath)
	for _, file := range files {
		if strings.HasPrefix(file.Name(), "~") || strings.Contains(file.Name(), "$") {
			fmt.Println("错误文件 " + file.Name()) //excel错误文件
			continue
		}
		if !strings.HasSuffix(file.Name(), ".xlsx") { //仅限xlsx xls不行
			fmt.Println("请使用.xlsx 文件 " + file.Name())
			continue
		}
		filePath := excelPath + "/" + file.Name()
		//fmt.Println("process:" + filePath)
		onceFile(filePath) //打开单个文件
	}

	ofiles, _ := ioutil.ReadDir(excelOther)
	for _, file := range ofiles {
		if strings.HasPrefix(file.Name(), "~") || strings.Contains(file.Name(), "$") {
			fmt.Println("错误文件 " + file.Name()) //excel错误文件
			continue
		}
		if !strings.HasSuffix(file.Name(), ".xlsx") { //仅限xlsx xls不行
			fmt.Println("请使用.xlsx 文件 " + file.Name())
			continue
		}
		filePath := excelOther + "/" + file.Name()
		//fmt.Println("process:" + filePath)
		onceFile(filePath) //打开单个文件
	}
}

func onceFile(filePath string) {
	xlsx, err := excelize.OpenFile(filePath)
	if err != nil {
		return
	}
	for index, name := range xlsx.GetSheetMap() {
		fmt.Println(index, name)
		onceSheet(xlsx, name) //打开一个Sheet
	}
}

func onceSheet(xlsx *excelize.File, sheetName string) {

	//获得整个表的数组(其实go里面叫切片)
	rows := xlsx.GetRows(sheetName)

	if !strings.Contains(sheetName, "|") {
		return
	}
	fmt.Println("process:" + sheetName)

	sheetNameArr := strings.Split(sheetName, "|")
	tbName := sheetNameArr[1]

	//获得 S L SL数据 L代表客户端 S代表服务器 SL代表客户端服务器共有数据
	slType := rows[0]
	//	fmt.Print(slType)

	//获得表类型数据 int string table
	dataType := rows[1]
	//	fmt.Print(dataType)

	//获得表类型数据 sn s_name
	dataName := rows[2]
	//	fmt.Print(dataName)

	var szLua = ""
	//szLua += getLuaColKey(slType, dataName)

	//snKey = {[1001]=1,[1002]=2,[1003]=3},
	szLua += "\tsnKey = {"
	for rowK, row := range rows {
		if rowK == 0 || rowK == 1 || rowK == 2 || rowK == 3 {
			continue
		}
		if len(row[0]) <= 0 { //会出现空串的情况就不导出
			continue
		}
		szLua += getLuaSnKey(rowK, row, slType, dataName)
		//fmt.Println(rowK)
	}
	szLua += "},\n"

	for rowK, row := range rows {
		if rowK == 0 || rowK == 1 || rowK == 2 || rowK == 3 {
			continue
		}
		if len(row[0]) <= 0 { //会出现空串的情况就不导出
			continue
		}
		szLua += getLuaRowsString(rowK, row, slType, dataType, dataName)
		//fmt.Println(rowK)
	}

	final := ""
	final += tbHead
	final += tbName
	final += "={\n"
	final += szLua
	final += "\n}\n\n"
	//final += getSuffixFun(tbHead + tbName)

	writeFileName := luaPath + luaFileHead + tbName + ".lua"
	ioutil.WriteFile(writeFileName, []byte(final), 0666)
}

func getSuffixFun(tableName string) string {
	var szLua = ""

	szLua = szLua + tableName + ".get = function( sn )\n"
	szLua = szLua + "	local liMax = #" + tableName + "\n"
	szLua = szLua + "	for i = 1, liMax do\n"
	//szLua = szLua + "		if sn == " + tableName + "[i].sn then\n"
	szLua = szLua + "		if sn == " + tableName + "[i].sn then\n"
	szLua = szLua + "			return " + tableName + "[i]\n"
	szLua = szLua + "		end\n"
	szLua = szLua + "	end\n"
	szLua = szLua + "\n"
	szLua = szLua + "	return nil\n"
	szLua = szLua + "end\n"
	szLua = szLua + "\n"
	szLua = szLua + "" + tableName + ".getBy = function( ... )\n"
	szLua = szLua + "	local ltbCondition = { }\n"
	szLua = szLua + "	local ltbResult = { }\n"
	szLua = szLua + "\n"
	szLua = szLua + "	local arg = { ... }\n"
	szLua = szLua + "	for k, v in ipairs( arg ) do\n"
	szLua = szLua + "		ltbCondition[k] = v\n"
	szLua = szLua + "	end\n"
	szLua = szLua + "\n"
	szLua = szLua + "	local liMax		= table.maxn( ltbCondition )\n"
	szLua = szLua + "	local liMaxTb	= table.maxn( " + tableName + " )\n"
	szLua = szLua + "	if liMax % 2 ~= 0 then\n"
	szLua = szLua + "		return nil\n"
	szLua = szLua + "	end\n"
	szLua = szLua + "\n"
	szLua = szLua + "	local liIndex = 1\n"
	szLua = szLua + "	for liIndex = 1, liMaxTb do\n"
	szLua = szLua + "		local lbIsMatch = true\n"
	szLua = szLua + "\n"
	szLua = szLua + "		for j = 1, liMax, 2 do\n"
	szLua = szLua + "			local lstrKey = ltbCondition[j]\n"
	szLua = szLua + "			local lVaule = ltbCondition[j+1]\n"
	szLua = szLua + "\n"
	szLua = szLua + "			if " + tableName + "[liIndex][lstrKey] ~= lVaule then\n"
	szLua = szLua + "				lbIsMatch = false\n"
	szLua = szLua + "				break\n"
	szLua = szLua + "			end\n"
	szLua = szLua + "		end\n"
	szLua = szLua + "\n"
	szLua = szLua + "		if lbIsMatch then\n"
	szLua = szLua + "			return " + tableName + "[liIndex]\n"
	szLua = szLua + "		end\n"
	szLua = szLua + "	end\n"
	szLua = szLua + "\n"
	szLua = szLua + "	return nil\n"
	szLua = szLua + "end\n"
	szLua = szLua + "\n"
	szLua = szLua + "" + tableName + ".findAll = function( )\n"
	szLua = szLua + "	return " + tableName + "\n"
	szLua = szLua + "end\n"

	return szLua
}

func typeof(v interface{}) string {
	switch t := v.(type) {
	case int:
		return "int"
	case float64:
		return "float64"
	case string:
		return "string"
	//... etc
	default:
		_ = t
		return "unknown"
	}
}

//整合所有行的key名 去对应一行子数组下标
func getLuaColKey(slType []string, dataName []string) string {
	// colKey = {sn=1, name=2, age=3, phone=4}, --getLuaColKey
	// snKey = {[1001]=1,[1002]=2,[1003]=3},
	// [1] = {1001,"小李",31,18087777777},
	// [2] = {1002,"小叶",33,18908888888},
	// [3] = {1003,"小卢",35,13699999999},
	clientRowLen := 0
	clientRowIdx := 0
	for _, slstr := range slType {
		if strings.Contains(slstr, "L") {
			clientRowLen++
		}
	}

	var szLua string
	szLua = szLua + "\tcolKey={"
	for colKey, keyName := range dataName {
		if slType[colKey] == "L" || slType[colKey] == "SL" {
			clientRowIdx++
			szLua = szLua + keyName + "=" + strconv.Itoa(clientRowIdx)
			if clientRowIdx < clientRowLen {
				szLua += ","
			}
		}
	}
	//	fmt.Print(szLua)
	szLua += "},\n"
	return szLua
}

//整合所有行的sn 去对应一行数组下标
func getLuaSnKey(rowK int, row []string, slType []string, dataName []string) string {
	//snKey = {[1001]=1,[1002]=2,[1003]=3},
	//[1001]=1, 该函数完成

	// clientRowLen := 0
	// clientRowIdx := 0
	// for _, slstr := range slType {
	// 	if strings.Contains(slstr, "L") {
	// 		clientRowLen++
	// 	}
	// }

	var szLua string
	szLua = szLua + "[" + row[0] + "]=" + strconv.Itoa(rowK-3) + ","
	// szLua = szLua + "\tcolKey={"
	// for colKey, keyName := range dataName {
	// 	if slType[colKey] == "L" || slType[colKey] == "SL" {
	// 		clientRowIdx++
	// 		szLua = szLua + keyName + "=" + strconv.Itoa(clientRowIdx)
	// 		if clientRowIdx < clientRowLen {
	// 			szLua += ","
	// 		}
	// 	}
	// }

	return szLua
}

//得到一行拼好的有效字符串
func getLuaRowsString(rowK int, row []string, slType []string, dataType []string, dataName []string) string {
	// colKey = {sn=1, name=2, age=3, phone=4}, --getLuaColKey
	// snKey = {[1001]=1,[1002]=2,[1003]=3},
	// [1] = {1001,"小李",31,18087777777}, --getLuaRowsString
	// [2] = {1002,"小叶",33,18908888888},
	// [3] = {1003,"小卢",35,13699999999},
	clientRowLen := 0
	clientRowIdx := 0
	for _, slstr := range slType {
		if strings.Contains(slstr, "L") {
			clientRowLen++
		}
	}

	var szLua string
	idx := strconv.Itoa(rowK - 3)
	szLua = szLua + "\t[" + idx + "]={"
	for colKey, colCell := range row {
		//		fmt.Print(len(row))
		if slType[colKey] == "L" || slType[colKey] == "SL" {
			clientRowIdx++
			if dataName[colKey] == "sn" || dataName[colKey] == "Sn" || dataName[colKey] == "SN" {
				//szLua = szLua + "\t[" + colCell + "]={"
				szLua = szLua + dataName[colKey] + "=" + colCell
				//szLua = szLua + colCell
				if clientRowIdx < clientRowLen {
					szLua += ","
				}

			} else if dataType[colKey] == "int" || dataType[colKey] == "Int" {

				szLua = szLua + dataName[colKey] + "=" + colCell
				//szLua = szLua + colCell
				if clientRowIdx < clientRowLen {
					szLua += ","
				}

			} else if dataType[colKey] == "string" || dataType[colKey] == "String" {
				szLua = szLua + dataName[colKey] + "=" + "\"" + colCell + "\""
				//szLua = szLua + "\"" + colCell + "\""
				if clientRowIdx < clientRowLen {
					szLua += ","
				}

			} else if dataType[colKey] == "array" || dataType[colKey] == "Array" ||
				dataType[colKey] == "attr" || dataType[colKey] == "Attr" {
				// 一个key 对应对个值
				//原格式
				//aaa~1~2~3$aaa~2~2~4
				// 输出格式
				// {
				//   {"aaa",1,2,3},
				//   {"aaa",2,2,4}
				// }
				szTable := dataName[colKey] + "="
				//szTable := ""
				szTable = szTable + "{"
				table := strings.Split(colCell, "$")
				if table[0] != "" {
					for ak, arr := range table {
						//						fmt.Print(arr)
						//if strings.Contains(colCell, "$") { //所有的全部统一为二维数组
						szTable = szTable + "{"
						//} //所有的全部统一为二维数组
						sonArr := strings.Split(arr, "~")
						for k, v := range sonArr {
							_, error := strconv.Atoi(v)
							if error != nil { //str
								szTable = szTable + "\"" + v + "\""
							} else { //int
								szTable = szTable + v
							}
							if k+1 < len(sonArr) {
								szTable += ","
							}
						}
						//if strings.Contains(colCell, "$") { //所有的全部统一为二维数组
						szTable = szTable + "}"
						//} //所有的全部统一为二维数组
						if ak+1 < len(table) {
							szTable += ","
						}
					}
				}
				szTable = szTable + "}"
				if clientRowIdx < clientRowLen {
					szTable += ","
				}
				szLua = szLua + szTable
			}
			//			fmt.Print(szLua)
		}

	}
	//	fmt.Print(szLua)
	szLua += "},\n"
	return szLua
}

//得到一行拼好的有效字符串
// func getJsonRowsString(xlsx *excelize.File, sheetName string) {

// }

//用于结束后暂停
func pause() {
	fmt.Println("请按任意键继续...")
Loop:
	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			break Loop
		}
	}
}

func main() {

	loadExcels()

	fmt.Println("done")
	pause()
}
